`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2024/07/28 11:25:43
// Design Name: 
// Module Name: SVPWM
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module SVPWM(
    input                   sys_clk_i           ,
    input                   sys_rst_n_i         ,

    input                   svpwm_en_i          ,
    output                  svpwm_ack_o         ,


    input signed[31:0]      Ualpha_i            ,
    input signed[31:0]      Ubeta_i             ,


    output reg[15:0]        pwm_ta              ,
    output reg[15:0]        pwm_tb              ,
    output reg[15:0]        pwm_tc          
);
`define SQRT3_div_2 $signed(32'd56755)      
`define K           $signed(32'd9459)           //扩大2^16
`define Ts          $signed(32'd2500)       //


reg[6:0]    cnt;
reg         dealing;

reg signed[31:0]    U1;
reg signed[31:0]    U2;
reg signed[31:0]    U3;
reg signed[31:0]    Ubeta_div2;
reg signed[63:0]    sqrt3_div2_mul_ualpha;

reg signed[63:0]    K_mul_U1;
reg signed[63:0]    K_mul_U2;
reg signed[63:0]    K_mul_U3;

reg signed[31:0]    TIME1;
reg signed[31:0]    TIME2;
reg signed[31:0]    TIME3;

reg signed[31:0]    Ta_temp;
reg signed[31:0]    Tb_temp;
reg signed[31:0]    Tc_temp;



reg A,B,C;
reg[3:0] N;
reg[5:0] sector;


assign svpwm_ack_o = ( cnt == 'd19 ) ? 1'b1 : 1'b0;

always@( posedge sys_clk_i or negedge sys_rst_n_i ) begin
    if( sys_rst_n_i == 1'b0 )
        dealing <= 1'b0;
    else if( svpwm_ack_o == 1'b1 )
        dealing <= 1'b0;
    else if( svpwm_en_i == 1'b1 )
        dealing <= 1'b1;
    else
        dealing <= 1'b0;
end

always@( posedge sys_clk_i or negedge sys_rst_n_i ) begin
    if( sys_rst_n_i == 1'b0 )
        cnt <= 'd0;
    else if( dealing == 1'b1 )
        cnt <= cnt + 1'b1;
    else
        cnt <= 'd0;
end


always@( posedge sys_clk_i or negedge sys_rst_n_i ) begin
    if( sys_rst_n_i == 1'b0 )
        U1 <= 'd0;
    else if( cnt == 'd1 ) 
        U1 <= Ubeta_i;
    else
        U1 <= U1;
end

always@( posedge sys_clk_i or negedge sys_rst_n_i ) begin
    if( sys_rst_n_i == 1'b0 )
        Ubeta_div2 <= 'd0;
    else if( cnt == 'd1 ) 
        Ubeta_div2 <= Ubeta_i >>> 1;
    else
        Ubeta_div2 <= Ubeta_div2;
end

always@( posedge sys_clk_i or negedge sys_rst_n_i ) begin
    if( sys_rst_n_i == 1'b0 )
        sqrt3_div2_mul_ualpha <= 'd0;
    else if( cnt == 'd1 ) 
        sqrt3_div2_mul_ualpha <= (`SQRT3_div_2 * Ualpha_i );
    else if( cnt == 'd3 )
        sqrt3_div2_mul_ualpha <= sqrt3_div2_mul_ualpha >>> 16;
    else
        sqrt3_div2_mul_ualpha <= sqrt3_div2_mul_ualpha;
end



always@( posedge sys_clk_i or negedge sys_rst_n_i ) begin
    if( sys_rst_n_i == 1'b0 )
        U2 <= 'd0;
    else if( cnt == 'd5 ) 
        U2 <= -( sqrt3_div2_mul_ualpha + Ubeta_div2);
    else
        U2 <= U2;
end

always@( posedge sys_clk_i or negedge sys_rst_n_i ) begin
    if( sys_rst_n_i == 1'b0 )
        U3 <= 'd0;
    else if( cnt == 'd5 ) 
        U3 <= sqrt3_div2_mul_ualpha - Ubeta_div2;
    else
        U3 <= U3;
end


always@( posedge sys_clk_i or negedge sys_rst_n_i ) begin
    if( sys_rst_n_i == 1'b0 ) begin
        K_mul_U1 <= 'd0;       
        K_mul_U2 <= 'd0;
        K_mul_U3 <= 'd0;
    end
    else if( cnt == 'd7 )  begin
        K_mul_U1 <= `K * U1;       
        K_mul_U2 <= `K * U2;
        K_mul_U3 <= `K * U3;
    end
    else if( cnt == 'd9 )  begin
        K_mul_U1 <= K_mul_U1 >>> 16;       
        K_mul_U2 <= K_mul_U2 >>> 16;
        K_mul_U3 <= K_mul_U3 >>> 16;
    end
    else;
end


always@( posedge sys_clk_i or negedge sys_rst_n_i ) begin
    if( sys_rst_n_i == 1'b0 )
        A <= 'd0;
    else if( cnt == 'd7 ) 
        if( U1[31] == 1'b0)
            A <= 1'b1;
        else
            A <= 1'b0;
    else
        A <= A;
end
always@( posedge sys_clk_i or negedge sys_rst_n_i ) begin
    if( sys_rst_n_i == 1'b0 )
        B <= 'd0;
    else if( cnt == 'd7 ) 
        if( U2[31] == 1'b0)
            B <= 1'b1;
        else
            B <= 1'b0;
    else
        B <= B;
end

always@( posedge sys_clk_i or negedge sys_rst_n_i ) begin
    if( sys_rst_n_i == 1'b0 )
        C <= 'd0;
    else if( cnt == 'd7 ) 
        if( U3[31] == 1'b0)
            C <= 1'b1;
        else
            C <= 1'b0;
    else
        C <= C;
end

always@( posedge sys_clk_i or negedge sys_rst_n_i ) begin
    if( sys_rst_n_i == 1'b0 )
        N <= 'd0;
    else if( cnt == 'd8 ) 
        N <= (A << 2) + (B << 1) + C;
    else
        N <= N;
end


always@( posedge sys_clk_i or negedge sys_rst_n_i ) begin
    if( sys_rst_n_i == 1'b0 )  
        sector <= 'd0;
    else if( cnt == 'd9 )
        case(N)
            5: sector <= 'd1;
            4: sector <= 'd2;
            6: sector <= 'd3;
            2: sector <= 'd4;
            3: sector <= 'd5;
        default: sector <= 'd6;
        endcase
    else
        sector <= sector;
end


always@( posedge sys_clk_i or negedge sys_rst_n_i ) begin
    if( sys_rst_n_i == 1'b0 )  
        TIME1 <= 'd0;
    else if( cnt == 'd11 )
        case(sector)
            1: TIME1 <= K_mul_U3;
            2: TIME1 <= -K_mul_U3;
            3: TIME1 <= K_mul_U1;
            4: TIME1 <= -K_mul_U1;
            5: TIME1 <= K_mul_U2;
            6: TIME1 <= -K_mul_U2;
        default: TIME1 <= -K_mul_U2;
        endcase
    else if( cnt == 'd12 )
        TIME1 <= TIME1 >>> 6;
    else
        TIME1 <= TIME1;
end
always@( posedge sys_clk_i or negedge sys_rst_n_i ) begin
    if( sys_rst_n_i == 1'b0 )  
        TIME2 <= 'd0;
    else if( cnt == 'd11 )
        case(sector)
            1: TIME2 <= K_mul_U1;
            2: TIME2 <= -K_mul_U2;
            3: TIME2 <= K_mul_U2;
            4: TIME2 <= -K_mul_U3;
            5: TIME2 <= K_mul_U3;
            6: TIME2 <= -K_mul_U1;
        default: TIME2 <= -K_mul_U1;
        endcase
    else if( cnt == 'd12 )
        TIME2 <= TIME2 >>> 6;
    else
        TIME2 <= TIME2;
end
always@( posedge sys_clk_i or negedge sys_rst_n_i ) begin
    if( sys_rst_n_i == 1'b0 )  
        TIME3 <= 'd0;
    else if( cnt == 'd13 )
        TIME3 <= `Ts - TIME1 - TIME2;
    else if( cnt == 'd14 )
        TIME3 <= TIME3 >>> 1;
    else
        TIME3 <= TIME3;
end

always@( posedge sys_clk_i or negedge sys_rst_n_i ) begin
    if( sys_rst_n_i == 1'b0 )  
        Ta_temp <= 'd0;
    else if( cnt == 'd15 )
        case(sector)
            1: Ta_temp <= TIME1 + TIME2 + TIME3;
            2: Ta_temp <= TIME2 + TIME3;
            3: Ta_temp <= TIME3;
            4: Ta_temp <= TIME3;
            5: Ta_temp <= TIME2 + TIME3;
            6: Ta_temp <= TIME1 + TIME2 + TIME3;
        default: Ta_temp <= -K_mul_U1;
        endcase
    else
        Ta_temp <= Ta_temp;
end

always@( posedge sys_clk_i or negedge sys_rst_n_i ) begin
    if( sys_rst_n_i == 1'b0 )  
        Tb_temp <= 'd0;
    else if( cnt == 'd15 )
        case(sector)
            1: Tb_temp <= TIME2 + TIME3;
            2: Tb_temp <= TIME1 + TIME2 + TIME3;
            3: Tb_temp <= TIME1 + TIME2 + TIME3;
            4: Tb_temp <= TIME2 + TIME3;
            5: Tb_temp <= TIME3;
            6: Tb_temp <= TIME3;
        default: Tb_temp <= -K_mul_U1;
        endcase
    else
        Tb_temp <= Tb_temp;
end

always@( posedge sys_clk_i or negedge sys_rst_n_i ) begin
    if( sys_rst_n_i == 1'b0 )  
        Tc_temp <= 'd0;
    else if( cnt == 'd15 )
        case(sector)
            1: Tc_temp <= TIME3;
            2: Tc_temp <= TIME3;
            3: Tc_temp <= TIME2 + TIME3;
            4: Tc_temp <= TIME1 + TIME2 + TIME3;
            5: Tc_temp <= TIME1 + TIME2 + TIME3;
            6: Tc_temp <= TIME2 + TIME3;
        default: Tc_temp <= -K_mul_U1;
        endcase
    else
        Tc_temp <= Tc_temp;
end

always@( posedge sys_clk_i or negedge sys_rst_n_i ) begin
  if( sys_rst_n_i == 1'b0 ) begin
    pwm_ta <= 'd0;
    pwm_tb <= 'd0;
    pwm_tc <= 'd0;
  end
  else if( cnt == 'd17 ) begin
    pwm_ta <= Ta_temp;
    pwm_tb <= Tb_temp;
    pwm_tc <= Tc_temp;
  end
  else;
end



// wire signed[63:0]       sqrt_u;
// reg  signed[63:0]       ubeta_div_2;

// wire signed[64:0]       U2_temp;
// wire signed[64:0]       U3_temp;

// reg  signed[31:0]       U1;
// reg  signed[31:0]       U2;
// reg  signed[31:0]       U3;

// wire signed[63:0]      K_mul_U1;
// wire signed[63:0]      K_mul_U2;
// wire signed[63:0]      K_mul_U3;

// reg signed[63:0]       T1;
// reg signed[63:0]       T2;
// wire signed[64:0]      T1_add_T2;
// reg  signed[63:0]      T1_add_T2_div_2;
// wire signed[64:0]      T_sub_T1T2;

// wire signed[64:0]      TIME1;
// wire signed[64:0]      TIME2;


// reg A;
// reg B;
// reg C;
// reg[3:0] N;
// reg[4:0] sector;


// wire mul_step_one_en;
// wire addsub_step_one_en;
// wire mul_step_two_en;
// wire addsub_step_two_en;
// wire addsub_step_three_en;
// wire addsub_step_four_en;
// reg[7:0]    cnt;


// assign svpwm_ack_o = ( cnt == 'd43 ) ? 1'b1 : 1'b0;

// assign mul_step_one_en    = ( cnt == 'd1 || cnt == 'd2 || cnt == 'd3 ) ?  1'b1 : 1'b0;
// assign addsub_step_one_en = ( cnt > 'd3 && cnt < 'd11) ?  1'b1 : 1'b0;
// assign mul_step_two_en    = ( cnt == 'd13 || cnt == 'd14 || cnt == 'd15) ? 1'b1 : 1'b0;
// assign addsub_step_two_en = ( cnt > 'd15 && cnt < 'd23) ? 1'b1 : 1'b0;
// assign addsub_step_three_en = ( cnt > 'd24 && cnt < 'd32) ? 1'b1 : 1'b0;
// assign addsub_step_four_en = ( cnt > 'd33 && cnt < 'd41) ? 1'b1 : 1'b0;


// always@( posedge sys_clk_i or negedge sys_rst_n_i ) begin
//     if( sys_rst_n_i == 1'b0 )
//         cnt <= 'd0;
//     else if( svpwm_en_i == 1'b1 )
//         cnt <= cnt + 1'b1;
//     else
//         cnt <= 'd0;
// end

// always@( posedge sys_clk_i ) begin
//     if( cnt == 'd1 )
//         ubeta_div_2 <= Ubeta_i <<< 15;
//     else if( cnt == 'd2)
//         ubeta_div_2 <= $signed(-ubeta_div_2);
//     else
//         ubeta_div_2 <= ubeta_div_2;
// end


// always@( posedge sys_clk_i ) begin
//     if( cnt == 'd12 )
//         U1 <= Ubeta_i;
//     else;
// end
// always@( posedge sys_clk_i ) begin
//     if( cnt == 'd12 )
//         U2 <= U2_temp >>> 16;
//     else;
// end
// always@( posedge sys_clk_i ) begin
//     if( cnt == 'd12 )
//         U3 <= U3_temp >>> 16;
//     else;
// end

// always@( posedge sys_clk_i ) begin
//     if( cnt == 'd13 && U1[31] == 1'b1 )
//         A <= 1'b0;
//     else if( cnt == 'd13 && U1[31] == 1'b0 )
//         A <= 1'b1;
//     else
//         A <= A;
// end
// always@( posedge sys_clk_i ) begin
//     if( cnt == 'd13 && U2[31] == 1'b1 )
//         B <= 1'b0;
//     else if( cnt == 'd13 && U2[31] == 1'b0 )
//         B <= 1'b1;
//     else
//         B <= B;
// end
// always@( posedge sys_clk_i ) begin
//     if( cnt == 'd13 && U3[31] == 1'b1 )
//         C <= 1'b0;
//     else if( cnt == 'd13 && U3[31] == 1'b0 )
//         C <= 1'b1;
//     else
//         C <= C;
// end
// always@( posedge sys_clk_i ) begin
//     N <= ( A << 2) + ( B << 1) + C;
// end 
// always@(posedge sys_clk_i ) begin
//     case(N)
//     5: sector <= 'd1;
//     4: sector <= 'd2;
//     6: sector <= 'd3;
//     2: sector <= 'd4;
//     3: sector <= 'd5;
//     default: sector <= 'd6;
//     endcase
// end

// always@(posedge sys_clk_i ) begin
//     if( cnt == 'd16) begin
//         case(sector) 
//         'd1: begin
//             T1 <= K_mul_U3;
//             T2 <= K_mul_U1;        
//         end
//         'd2: begin
//             T1 <= $signed(-K_mul_U3);
//             T2 <= $signed(-K_mul_U2);        
//         end
//         'd3: begin
//             T1 <= $signed(K_mul_U1);
//             T2 <= $signed(K_mul_U2);        
//         end
//         'd4: begin
//             T1 <= $signed(-K_mul_U1);
//             T2 <= $signed(-K_mul_U3);        
//         end
//         'd5: begin
//             T1 <= $signed(K_mul_U2);
//             T2 <= $signed(K_mul_U3);        
//         end
//         'd6: begin
//             T1 <= $signed(-K_mul_U2);
//             T2 <= $signed(-K_mul_U1);        
//         end
//         endcase
//     end
// end


// always@( posedge sys_clk_i ) begin
//     if( cnt == 'd24 )
//         T1_add_T2_div_2 <= T1_add_T2 >>> 1;
//     else;
// end

// always@(posedge sys_clk_i ) begin
//     if( cnt == 'd42) begin
//         case(sector)
//         'd1: begin
//             pwm_ta <= TIME1         >>> 14;
//             pwm_tb <= TIME2         >>> 14;  
//             pwm_tc <= T_sub_T1T2    >>> 14;        
//         end
//         'd2: begin
//             pwm_ta <= TIME2         >>> 14;
//             pwm_tb <= TIME1         >>> 14;  
//             pwm_tc <= T_sub_T1T2    >>> 14;        
//         end
//         'd3: begin
//             pwm_ta <= T_sub_T1T2    >>> 14;
//             pwm_tb <= TIME1         >>> 14;  
//             pwm_tc <= TIME2         >>> 14;         
//         end
//         'd4: begin
//             pwm_ta <= T_sub_T1T2    >>> 14;
//             pwm_tb <= TIME2         >>> 14;  
//             pwm_tc <= TIME1         >>> 14;     
//         end
//         'd5: begin
//             pwm_ta <= TIME2         >>> 14;
//             pwm_tb <= T_sub_T1T2    >>> 14;  
//             pwm_tc <= TIME1         >>> 14;         
//         end
//         'd6: begin
//             pwm_ta <= TIME1         >>> 14;
//             pwm_tb <= T_sub_T1T2    >>> 14;  
//             pwm_tc <= TIME2         >>> 14;          
//         end
//         endcase
//     end
// end



// // ----------   step one ----------------------
// assign sqrt_u = Ualpha_i * `SQRT3_div_2;
// // mult_gen_32_32 mult_gen_32_32_sqrt_u
// // (
// //     .CLK        (       sys_clk_i       ),  
// //     .A          (       Ualpha_i        ),
// //     .B          (       `SQRT3_div_2    ),  
// //     .CE         (       mul_step_one_en ),
// //     .P          (       sqrt_u          )
// // );

// // ----------   step two ----------------------
// assign U2_temp = ubeta_div_2 - sqrt_u;
// // c_addsub_64 c_addsub_64_U2_temp
// // (
// //     .A          (       ubeta_div_2     ),
// //     .B          (       sqrt_u          ),
// //     .CLK        (       sys_clk_i       ),
// //     .ADD        (       1'b0            ),
// //     .CE         (       addsub_step_one_en),
// //     .S          (       U2_temp         )
// // );
// assign U3_temp = ubeta_div_2 + sqrt_u;
// // c_addsub_64 c_addsub_64_U3_temp
// // (
// //     .A          (       ubeta_div_2     ),
// //     .B          (       sqrt_u          ),
// //     .CLK        (       sys_clk_i       ),
// //     .ADD        (       1'b1            ),
// //     .CE         (       addsub_step_one_en),
// //     .S          (       U3_temp         )
// // );







// // ----------   step three ----------------------
// assign K_mul_U1 = U1 * `K;
// // mult_gen_32_32 mult_gen_32_32_K_mul_U1
// // (
// //     .CLK        (       sys_clk_i       ),  
// //     .A          (       U1              ),
// //     .B          (       `K              ),  
// //     .CE         (       mul_step_two_en ),
// //     .P          (       K_mul_U1        )
// // );
// assign K_mul_U2 = U2 * `K;
// // mult_gen_32_32 mult_gen_32_32_K_mul_U2
// // (
// //     .CLK        (       sys_clk_i       ),  
// //     .A          (       U2              ),
// //     .B          (       `K              ),  
// //     .CE         (       mul_step_two_en ),
// //     .P          (       K_mul_U2        )
// // );
// assign K_mul_U3 = U3 * `K;
// // mult_gen_32_32 mult_gen_32_32_K_mul_U3
// // (
// //     .CLK        (       sys_clk_i       ),  
// //     .A          (       U3              ),
// //     .B          (       `K              ),  
// //     .CE         (       mul_step_two_en ),
// //     .P          (       K_mul_U3        )
// // );

// // ----------   step four ----------------------
// assign T1_add_T2 = T1 + T2;

// // c_addsub_64 c_addsub_64_T1_add_T2
// // (
// //     .A          (       T1              ),
// //     .B          (       T2              ),
// //     .CLK        (       sys_clk_i       ),
// //     .ADD        (       1'b1            ),
// //     .CE         (       addsub_step_two_en),
// //     .S          (       T1_add_T2       )
// // );

// assign T_sub_T1T2 = `Ts - T1_add_T2_div_2;
// // c_addsub_64 c_addsub_64_T_sub_T1T2
// // (
// //     .A          (       `Ts             ),
// //     .B          (       T1_add_T2_div_2 ),
// //     .CLK        (       sys_clk_i       ),
// //     .ADD        (       1'b0            ),
// //     .CE         (       addsub_step_three_en),
// //     .S          (       T_sub_T1T2       )
// // );


// // ----------   step five ----------------------
// assign TIME1 = T_sub_T1T2[63:0] + T1_add_T2;
// // c_addsub_64 c_addsub_64_TIME1
// // (
// //     .A          (       T_sub_T1T2[63:0]),
// //     .B          (       T1_add_T2       ),
// //     .CLK        (       sys_clk_i       ),
// //     .ADD        (       1'b1            ),
// //     .CE         (       addsub_step_four_en),
// //     .S          (       TIME1           )
// // );
// assign TIME2 = T_sub_T1T2[63:0] + T2; 
// // c_addsub_64 c_addsub_64_TIME2
// // (
// //     .A          (       T_sub_T1T2[63:0]),
// //     .B          (       T2              ),
// //     .CLK        (       sys_clk_i       ),
// //     .ADD        (       1'b1            ),
// //     .CE         (       addsub_step_four_en),
// //     .S          (       TIME2           )
// // );




















endmodule
